import org.junit.Test;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * @author liweimin
 * @date 2020/10/17 9:38
 * @description Channel： 用于源节点和目标节点的连接，在Java NIO中负责数据的传输，Channel本身不传输数据需要配合缓冲区
 * 通道的主要实现类：
 * java.nio.channels.Channel 接口：
 * |--FileChannel
 * |--SocketChannel
 * |--ServerSocketChannel
 * |--DatagramChannel
 */
public class ChannelTest {
    @Test
    public void test01() throws IOException {
        //1.利用通道完成文件复制（非直接缓冲区）
        FileInputStream fileInputStream = new FileInputStream("src" + File.separator + "1.jpg");
        FileOutputStream fileOutputStream = new FileOutputStream("2.jpg");
        //获取通道Files.newByteChannel() open()
        FileChannel channel = fileInputStream.getChannel();
        FileChannel channel1 = fileOutputStream.getChannel();
        //分配缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(4096);
        //将通道中的数据存入缓冲区
        while (channel.read(buffer) != -1) {
            //切换读数据模式
            buffer.flip();
            //将缓冲区数据写入通道
            channel1.write(buffer);
            //清空缓冲区
            buffer.clear();
        }
        channel1.close();
        channel.close();
        fileOutputStream.close();
        fileInputStream.close();
    }

    @Test
    public void test02() throws IOException {
        //使用直接缓冲区完成文件的赋值（内存映射文件）-----》直接操作缓冲区 不需要涉及到通道
        FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
        FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE_NEW);
        //内存映射文件
        MappedByteBuffer Inmap = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
        MappedByteBuffer Outmap = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
        //直接对缓冲区进行读写操作
        byte[] bytes = new byte[Inmap.limit()];
        Inmap.get(bytes);
        Outmap.put(bytes);
        inChannel.close();
        outChannel.close();
//System.gc();
    }

    @Test
    public void test03() throws IOException {
        //通道之间的数据传输（直接缓冲区）
        FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
        FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE_NEW);
        outChannel.transferFrom(inChannel, 0, inChannel.size());
//    inChannel.transferTo(outChannel, 0, outChannel.size());
        inChannel.close();
        outChannel.close();
    }

    @Test
    public void test04() throws FileNotFoundException {
        /**
         * Scatter AND Gather
         * Scatter： Scattering Reads 分散读取：将通道中的数据分散到多个缓冲区中
         * Gather：  Gathering Writes 聚集写入：将多个缓冲区的数据聚集到缓冲区中
         */
        RandomAccessFile file = new RandomAccessFile("1.txt", "rw");
        //获得通道
        FileChannel channel = file.getChannel();
        /**
         * hfsk ljfskjl
         */
    }
}
